/**
 * Generali Solutions d'assurances - Tous droits réservés &copy; 2007 - 2010
 */
package fr.generali.accueilclient.client.services.impl;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import fr.generali.accueilclient.client.om.IClientAssociation;
import fr.generali.accueilclient.client.om.IClientAutre;
import fr.generali.accueilclient.client.om.IClientEntreprise;
import fr.generali.accueilclient.client.om.IClientProfessionnel;
import fr.generali.accueilclient.client.om.IDonneeMarketing;
import fr.generali.accueilclient.client.om.IPersonne;
import fr.generali.accueilclient.client.om.impl.DonneeMarketing;
import fr.generali.accueilclient.commun.exception.AccueilClientBusinessException;
import fr.generali.accueilclient.utils.constantes.IConstantes;
import fr.generali.accueilclient.utils.stringbuilder.StringBuilderUtils;
import fr.generali.refservcommuns.clients.resume.rechercheparidentifiantnonqualifieservice.v4.ctr.structurecontrat.DtoContrat;
import fr.generali.refservcommuns.rce.consultdonneesmarketing.ConsulterDonneesMarketingResponse;
import fr.generali.refservcommuns.rce.consultdonneesmarketing.donneesmarketing.DtoDonneesMarketing;
import fr.generali.refservcommuns.rce.consultdonneesmarketing.donneesmarketing.DtoDossierMarketing;
import fr.generali.refservcommuns.rce.consultdonneesmarketing.donneesmarketing.DtoListeDossiersMarketing;
import fr.generali.refservcommuns.rce.consultindicateursclient.ConsulterIndicateursClientResponse;
import fr.generali.refservcommuns.rce.consultindicateursclient.dossierpersonneindicateurs.DtoListeDossierP19;
import fr.generali.refservcommuns.rce.consultindicateursclient.pty.profilmarketingpersonnes.DtoProfilMarketing;
import fr.generali.refservcommuns.rce.consultpersonnecontact.ConsulterPersonneContactResponse;
import fr.generali.refservcommuns.rce.consultpersonnecontact.dossierpersonnecontact.DtoDossierP42;
import fr.generali.refservcommuns.rce.consultpersonnecontact.dossierpersonnecontact.DtoListeDossierP42;
import fr.generali.refservcommuns.rce.demat.consultpersonneenvcomplet.ConsulterPersonneEnvCompletResponse;
import fr.generali.refservcommuns.rce.demat.consultpersonneenvcomplet.dossierpersonneenvcomplet.DtoDossierP44;
import fr.generali.refservcommuns.rce.demat.consultpersonneenvcomplet.dossierpersonneenvcomplet.DtoListeDossierP44;
import fr.generali.refservcommuns.rce.consultpersonnesimple.ConsulterPersonneSimpleResponse;
import fr.generali.refservcommuns.rce.consultpersonnesimple.dossierpersonnesimple.DtoDossierP41;
import fr.generali.refservcommuns.rce.consultpersonnesimple.dossierpersonnesimple.DtoListeDossierP41;
import fr.generali.refservcommuns.rce.recherche.nonqualifie.dossier.identifiant.DossierRechercheParIdentifiant;
import fr.generali.refservcommuns.rce.recherche.nonqualifie.pty.personnes.DTOPersonneResume;
import fr.generali.refservcommuns.rce.rechpersgen.extrait.DtoDossierPersonneExtrait;
import fr.generali.refservcommuns.rce.restitutionpersonne.dossier.listedossierpersonnep10.DtoListeDossierPersonneP10;
import fr.generali.refservcommuns.rce.restitutionpersonne.restitutionpersonnebyidservice.RestitutionPersonneByIdResponse;
import fr.generali.refservcommuns.rce.searchgenerique.dossier.listedossierpersonnep2.DtoListeDossierPersonneP2;
import fr.generali.refservcommuns.rce.searchgenerique.recherchepersonnegeneriqueservice.RechercherPersonnesGeneriqueResponse;

/**
 * Classe de mapper utilisée par {@link ClientService}
 * 
 * @author selrhazala
 */
@Component("clientServiceMapper")
public class ClientServiceMapper {

    /**
     * LOGGER
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ClientServiceMapper.class);

    /**
     * Nombre de résultats max de la recherche
     */
    private static final BigInteger MAX_RESULT = BigInteger.valueOf(50);

    /**
     * Clé du message d'erreur fonctionnelle
     */
    private static final String TOO_MANY_RESULTS = "recherche.form.client.resultat.trop.large";

    /**
     * L'assembler pour P41
     */
    @Autowired
    @Qualifier("dtoDossierP41ToPersonneConverter")
    private Converter<DtoDossierP41, IPersonne> dtoDossierP41ToPersonneConverter;

    /**
     * L'assembler pour P42
     */
    @Autowired
    @Qualifier("dtoDossierP42ToPersonneConverter")
    private Converter<DtoDossierP42, IPersonne> dtoDossierP42ToPersonneConverter;

    /**
     * L'assembler pour P44
     */
    @Autowired
    @Qualifier("dtoDossierP44ToPersonneConverter")
    private Converter<DtoDossierP44, IPersonne> dtoDossierP44ToPersonneConverter;

    /**
     * L'assembler pour P2bis
     */
    @Autowired
    @Qualifier("dtoDossierPersonneExtrait2PersonneConverter")
    private Converter<DtoDossierPersonneExtrait, IPersonne> dtoDossierPersonneExtrait2PersonneConverter;

    /**
     * L'assembler Personne pour P10 Non Qualifie
     */
    @Autowired
    @Qualifier("dtoPersonneResume2PersonneConverter")
    private Converter<DTOPersonneResume, IPersonne> dtoPersonneResume2PersonneConverter;

    /**
     * L'assembler contrat pour P10 Non Qualifie
     */
    @Autowired
    @Qualifier("dtoContrat2PersonneConverter")
    private Converter<DtoContrat, IPersonne> dtoContrat2PersonneConverter;

    /**
     * L'assembler contrat pour S10 Non Qualifie
     */
    @Autowired
    @Qualifier("dtoContrat2ListPersonneConverter")
    private Converter<DtoContrat, List<IPersonne>> dtoContrat2ListPersonneConverter;

    /**
     * Transforme un {@link ConsulterPersonneContactResponse} en un
     * {@link IPersonne}
     * 
     * @param response la réponse de la consultation client contact
     * @return un {@link IPersonne}
     */
    public IPersonne mapperLectureClientContact(ConsulterPersonneContactResponse response) {
        LOGGER.info("mapperLectureClientContact");
        IPersonne personne = mapperDossierP42(response.getDtoListeDossierP42());
        if (personne != null) {
            personne.setFullLoaded(true);
        }
        return personne;
    }

    /**
     * Transforme un {@link ConsulterPersonneSimpleResponse} en un
     * {@link IPersonne}
     * 
     * @param response la réponse de la consultation client simple
     * @return un {@link IPersonne}
     */
    public IPersonne mapperLectureClientSimple(ConsulterPersonneSimpleResponse response) {
        LOGGER.info("mapperLectureClientSimple");
        IPersonne personne = mapperDossierP41(response.getDtoListeDossierP41());
        if (personne != null) {
            personne.setFullLoaded(false);
        }
        return personne;
    }

    /**
     * Transforme un {@link ConsulterPersonneEnvCompletResponse} en un
     * {@link IPersonne}
     * 
     * @param response la réponse de la consultation client avec son
     *            environnement
     * @return un {@link IPersonne}
     */
    public IPersonne mapperLectureClientEnvironnementComplet(ConsulterPersonneEnvCompletResponse response) {
        LOGGER.info("mapperLectureClientEnvironnementComplet");
        IPersonne personne = mapperDossierP44(response.getDtoListeDossierP44());
        if (personne != null) {
            personne.setFullLoaded(true);
        }
        return personne;
    }

    /**
     * Transforme un {@link ConsulterDonneesMarketingResponse} en un
     * {@link IPersonne}
     * 
     * @param response la réponse de la consultation du Profil Marketing client
     * @return IDonneeMarketing {@link IDonneeMarketing}
     */
    public IDonneeMarketing mapperProfilMarketingClient(ConsulterDonneesMarketingResponse response) {
        LOGGER.info("mapperProfilMarketingClient");

        DtoListeDossiersMarketing listeDossiers = response.getDtoListeDossiersMarketing();
        List<DtoDossierMarketing> listeDto = listeDossiers.getListeDossiers();

        DtoDossierMarketing dtoDossierMarketing = null;
        IDonneeMarketing donneeMarketing = null;
        DtoDonneesMarketing dtoDonneesMarketing = null;
        if (CollectionUtils.isNotEmpty(listeDto)) {
            dtoDossierMarketing = listeDto.get(0);

            for (int j = 0; j < dtoDossierMarketing.getDonneesMarketing().size(); j++) {
                donneeMarketing = new DonneeMarketing();
                dtoDonneesMarketing = dtoDossierMarketing.getDonneesMarketing().get(j);

                if (dtoDonneesMarketing != null) {
                    if (dtoDonneesMarketing.getCodeDonneesMarketing().equalsIgnoreCase(IConstantes.TYPE_DE_CLIENT_PART)) {
                        donneeMarketing.setTypeProfilMarketing(dtoDonneesMarketing.getCodeIndicateurMarketing()
                                        + StringBuilderUtils.SEPARATOR_TIRET_ESPACE
                                        + dtoDonneesMarketing.getCodeDonneesMarketing());
                    }

                    if (dtoDonneesMarketing.getCodeIndicateurMarketing().equalsIgnoreCase(
                                    IConstantes.PRODUITS_A_PROPOSER_PART)) {
                        donneeMarketing.setProduitProfilMarketing(dtoDonneesMarketing.getCodeIndicateurMarketing()
                                        + StringBuilderUtils.SEPARATOR_TIRET_ESPACE
                                        + dtoDonneesMarketing.getCodeDonneesMarketing());
                    }

                    if (dtoDonneesMarketing.getCodeIndicateurMarketing().equalsIgnoreCase(IConstantes.PROFIL_CLIENT_PART)) {
                        donneeMarketing.setClientProfilMarketing(dtoDonneesMarketing.getCodeIndicateurMarketing()
                                        + StringBuilderUtils.SEPARATOR_TIRET_ESPACE
                                        + dtoDonneesMarketing.getCodeDonneesMarketing());
                    }

                    if (dtoDonneesMarketing.getCodeIndicateurMarketing().equalsIgnoreCase(IConstantes.RISQUE_DEPART_PART)) {
                        donneeMarketing.setRisqueProfilMarketing(dtoDonneesMarketing.getCodeIndicateurMarketing()
                                        + StringBuilderUtils.SEPARATOR_TIRET_ESPACE
                                        + dtoDonneesMarketing.getCodeDonneesMarketing());
                    }
                    if (dtoDonneesMarketing.getCodeIndicateurMarketing().equalsIgnoreCase(
                                    IConstantes.ARGUMENTAIRE_DE_VENTE_PART)) {
                        donneeMarketing.setArgumentaireDeVente(dtoDonneesMarketing.getCodeIndicateurMarketing()
                                        + StringBuilderUtils.SEPARATOR_TIRET_ESPACE
                                        + dtoDonneesMarketing.getCodeDonneesMarketing());
                    }
                }
                // donneeMarketing.setCodeDonneesMarketing(dtoDonneesMarketing.getCodeDonneesMarketing());
                // donneeMarketing.setCodeIndicateurMarketing(dtoDonneesMarketing.getCodeIndicateurMarketing());
            }
        }

        return donneeMarketing;
    }

    /**
     * @param dto un {@link DtoListeDossierP42}
     * @return une personne
     */
    private IPersonne mapperDossierP41(DtoListeDossierP41 dto) {
        IPersonne personne = null;
        if (dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            DtoDossierP41 dtoDossierPersonne = dto.getDossierPersonne().get(0);
            personne = dtoDossierP41ToPersonneConverter.convert(dtoDossierPersonne);
        }

        return personne;
    }

    /**
     * @param dto un {@link DtoListeDossierP42}
     * @return une personne
     */
    private IPersonne mapperDossierP42(DtoListeDossierP42 dto) {
        IPersonne personne = null;
        if (dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            DtoDossierP42 dtoDossierPersonne = dto.getDossierPersonne().get(0);
            personne = dtoDossierP42ToPersonneConverter.convert(dtoDossierPersonne);
        }

        return personne;
    }

    /**
     * @param dto un {@link DtoListeDossierP44}
     * @return une personne
     */
    private IPersonne mapperDossierP44(DtoListeDossierP44 dto) {
        IPersonne personne = null;
        if (dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            DtoDossierP44 dtoDossierPersonne = dto.getDossierPersonne().get(0);
            personne = dtoDossierP44ToPersonneConverter.convert(dtoDossierPersonne);
        }

        return personne;
    }

    /**
     * Transforme un {@link RechercherPersonnesGeneriqueResponse} en une liste
     * de {@link IPersonne}
     * 
     * @param response la réponse de la recherche client
     * @return une liste de {@link IPersonne}
     * @exception AccueilClientBusinessException Exception business
     */
    public List<IPersonne> mapperRechercheClientGenerique(RechercherPersonnesGeneriqueResponse response)
                    throws AccueilClientBusinessException {
        LOGGER.info("mapperRechercheClientGenerique");
        DtoListeDossierPersonneP2 dto = response.getDtoListeDossierPersonneP2();
        if (response != null && dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonneP2())) {

            if (dto.getNombreEnregistrements().compareTo(MAX_RESULT) == 1 || dto.isReponsePartielle()) {
                throw new AccueilClientBusinessException(TOO_MANY_RESULTS, TOO_MANY_RESULTS);
            }

            List<IPersonne> liste = new ArrayList<IPersonne>();
            for (Iterator<DtoDossierPersonneExtrait> it = dto.getDossierPersonneP2().iterator(); it.hasNext();) {
                liste.add(dtoDossierPersonneExtrait2PersonneConverter.convert(it.next()));
            }

            return liste;
        }
        return null;
    }

    /**
     * Transforme un {@link RestitutionPersonneByIdResponse} en une liste de
     * {@link IPersonne}
     * 
     * @param response la réponse de la recherche client par identifiant
     * @return une liste de {@link IPersonne}
     */
    public List<IPersonne> mapperRechercheClientParId(RestitutionPersonneByIdResponse response) {
        LOGGER.info("mapperRechercheClientParId");
        DtoListeDossierPersonneP10 dto = response.getDtoListeDossierPersonneP10();
        if (response != null && dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonneById())) {

            List<IPersonne> liste = new ArrayList<IPersonne>();
            for (Iterator<DtoDossierPersonneExtrait> it = dto.getDossierPersonneById().iterator(); it.hasNext();) {
                liste.add(dtoDossierPersonneExtrait2PersonneConverter.convert(it.next()));
            }

            return liste;
        }
        return null;
    }

    /**
     * Transforme un {@link DossierRechercheParIdentifiant} en une liste de
     * {@link IPersonne}
     * 
     * @param response la réponse de la recherche client par identifiant
     * @return une liste de {@link IPersonne}
     */
    public List<IPersonne> mapperRechercheClientParIdNonQuailifie(DossierRechercheParIdentifiant response) {
        List<IPersonne> liste = null;

        LOGGER.info("mapperRechercheClientParIdNonQuailifie");
        if (response != null && CollectionUtils.isNotEmpty(response.getPersonnes())) {
            liste = new ArrayList<IPersonne>();
            for (Iterator<DTOPersonneResume> it = response.getPersonnes().iterator(); it.hasNext();) {
                liste.add(dtoPersonneResume2PersonneConverter.convert(it.next()));
            }

        } else if (response != null && CollectionUtils.isNotEmpty(response.getContrats())) {
            liste = new ArrayList<IPersonne>();
            for (Iterator<DtoContrat> it = response.getContrats().iterator(); it.hasNext();) {
                liste.add(dtoContrat2PersonneConverter.convert(it.next()));
            }

        }

        return liste;
    }

    /**
     * Mapping a implementer lors de la recherche via le service S10Nonqualifie
     * a la place de la methode <u> mapperRechercheClientParIdNonQuailifie </u>
     * dans une future livraison par rapport a un DtoContrat possedant plusieurs
     * roles
     * 
     * @param response la réponse de la recherche client par identifiant
     * @return une liste de personne
     */
    public List<IPersonne> mapperRechercheListeClientParIdNonQuailifie(DossierRechercheParIdentifiant response) {
        List<IPersonne> liste = null;

        LOGGER.info("mapperRechercheClientParIdNonQuailifie");
        if (response != null && CollectionUtils.isNotEmpty(response.getPersonnes())) {
            liste = new ArrayList<IPersonne>();
            for (Iterator<DTOPersonneResume> it = response.getPersonnes().iterator(); it.hasNext();) {
                liste.add(dtoPersonneResume2PersonneConverter.convert(it.next()));
            }

        } else if (response != null && CollectionUtils.isNotEmpty(response.getContrats())) {
            liste = new ArrayList<IPersonne>();
            for (Iterator<DtoContrat> it = response.getContrats().iterator(); it.hasNext();) {
                liste.addAll(dtoContrat2ListPersonneConverter.convert(it.next()));
            }

        }

        return liste;
    }

    /**
     * Transforme un {@link ConsulterPersonneContactResponse} en une liste de
     * {@link IPersonne}
     * 
     * @param response la réponse de la consultation client contact
     * @return une liste de {@link IPersonne}
     */
    public List<IPersonne> mapperRechercheClientParNumeroClientAgent(ConsulterPersonneContactResponse response) {
        LOGGER.info("mapperRechercheClientParNumeroClientAgent");
        List<IPersonne> clients = null;

        DtoListeDossierP42 dto = response.getDtoListeDossierP42();
        if (response != null && dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            List<DtoDossierP42> listePersonnes = dto.getDossierPersonne();
            clients = new ArrayList<IPersonne>(listePersonnes.size());
            IPersonne personne;
            for (DtoDossierP42 dossier : listePersonnes) {
                personne = dtoDossierP42ToPersonneConverter.convert(dossier);
                clients.add(personne);
            }
        }

        return clients;
    }

    /**
     * Transforme un {@link ConsulterIndicateursClientResponse} en une liste de
     * {@link IPersonne}
     * 
     * @param response la réponse des indicateurs client
     * @param client le client
     * @return client {@link IPersonne}
     */
    public IPersonne mapperIndicateursClient(ConsulterIndicateursClientResponse response, IPersonne client) {
        LOGGER.info("mapperIndicateursClient");
        DtoListeDossierP19 dto = response.getDtoListeDossierP19();
        if (response != null && dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            DtoProfilMarketing profilMarketing =
                            response.getDtoListeDossierP19().getDossierPersonne().get(0).getProfilMarketing();
            if (profilMarketing != null) {
                if (profilMarketing.getNombreBiensImmobiliers() != null) {

                    switch (client.getNaturePersonne()) {
                        case PARTICULIER:
                            client.setNbResidences(profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        case PROFESSIONNEL:
                            client.setNbResidences(profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        case ASSOCIATION:
                            IClientAssociation.class.cast(client).setNbSites(
                                            profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        case COLLECTIVITE:
                            client.setNbResidences(profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        case COPROPRIETE:
                            client.setNbResidences(profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        case ENTREPRISE:
                            IClientEntreprise.class.cast(client).setNbSites(
                                            profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                        default:
                            IClientAutre.class.cast(client).setNbSites(
                                            profilMarketing.getNombreBiensImmobiliers().toString());
                            break;
                    }
                }
                if (profilMarketing.getNombreVehicules() != null) {
                    client.setNbVehicules(profilMarketing.getNombreVehicules().toString());
                }
                if (profilMarketing.isPollicitable() != null) {
                    client.setPollicitable(profilMarketing.isPollicitable());
                }
                if (profilMarketing.isAssurableEnSante() != null) {
                    client.setAssurableEnSante(profilMarketing.isAssurableEnSante());
                }
            }
        }

        return client;
    }

    /**
     * Transforme un {@link ConsulterIndicateursClientResponse} en une liste de
     * {@link IPersonne}
     * 
     * @param response la réponse des indicateurs client
     * @param client le client
     * @return client {@link IPersonne}
     */
    public IPersonne mapperIndicateursClientPro(ConsulterIndicateursClientResponse response, IClientProfessionnel client) {

        LOGGER.info("mapperIndicateursClient");
        DtoListeDossierP19 dto = response.getDtoListeDossierP19();
        if (response != null && dto != null && CollectionUtils.isNotEmpty(dto.getDossierPersonne())) {
            DtoProfilMarketing profilMarketing =
                            response.getDtoListeDossierP19().getDossierPersonne().get(0).getProfilMarketing();
            if (profilMarketing != null) {
                if (profilMarketing.getNombreBiensImmobiliers() != null) {
                    client.getSphereProfessionnelle()
                                    .setNbSites(profilMarketing.getNombreBiensImmobiliers().toString());
                }
                if (profilMarketing.getNombreVehicules() != null) {
                    client.getSphereProfessionnelle().setNbVehicules(profilMarketing.getNombreVehicules().toString());
                }
            }
        }

        return client;
    }

}
